package com.biz.primus.ms.depot.service;

import com.biz.primus.base.enums.CommonStatus;
import com.biz.primus.base.exception.utils.AssertUtils;
import com.biz.primus.common.utils.CopyUtils;
import com.biz.primus.model.depot.exception.DepotException;
import com.biz.primus.model.depot.vo.FreightTemplateDetailRespVo;
import com.biz.primus.model.depot.vo.FreightTemplateUpdateReqVo;
import com.biz.primus.ms.base.service.AbstractBaseService;
import com.biz.primus.ms.depot.dao.po.FreightTemplate;
import com.biz.primus.ms.depot.dao.redis.FreightTemplateRedisDao;
import com.biz.primus.ms.depot.dao.repository.FreightTemplateRepository;
import com.biz.primus.ms.depot.dao.ro.FreightTemplateRo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;

/**
 * FreightTemplateService
 *
 * @author JKLiues
 * @date 2017年11月03日
 */
@Service
@Slf4j
public class FreightTemplateService extends AbstractBaseService {

    private final FreightTemplateRepository freightTemplateRepository;

    private final FreightTemplateRedisDao freightTemplateRedisDao;


    @Autowired
    public FreightTemplateService(FreightTemplateRepository freightTemplateRepository, FreightTemplateRedisDao freightTemplateRedisDao) {
        this.freightTemplateRepository = freightTemplateRepository;
        this.freightTemplateRedisDao = freightTemplateRedisDao;
    }


    /**
     * 更新或编辑运费模板
     *
     * @param reqVo 修改对象VO
     */
    @Transactional(rollbackFor = Exception.class)
    public void editFreightTemplate(FreightTemplateUpdateReqVo reqVo) {
        FreightTemplate template;
        Boolean unique = true;
        if (StringUtils.isBlank(reqVo.getId())) {
            template = new FreightTemplate();
            template.setId(idService.getNextId());
        } else {
            Long id = Long.valueOf(reqVo.getId());
            template = freightTemplateRepository.findOne(id);
            unique = checkCodeExists(id, reqVo.getFreightCode());
        }
        AssertUtils.notNull(template, DepotException.FREIGHT_NOT_EXISTS);
        AssertUtils.isTrue(unique, DepotException.FREIGHT_CODE_IS_EXIST);
        CopyUtils.copyProperties(reqVo, template);
        freightTemplateRepository.save(template);
        FreightTemplateRo ro = new FreightTemplateRo();
        CopyUtils.copyProperties(template, ro);
        delayer.executeAfterTransactionCommit(() -> freightTemplateRedisDao.save(ro));
    }

    /**
     * 更新运费模板可用状态
     *
     * @param id     运费模版Id
     * @param status 状态
     */
    @Transactional(rollbackFor = Exception.class)
    public void changeStatus(Long id, CommonStatus status) {
        AssertUtils.notNull(id, DepotException.FREIGHT_ID_IS_NULL);
        FreightTemplate template = freightTemplateRepository.findOne(id);
        AssertUtils.notNull(template, DepotException.FREIGHT_NOT_EXISTS);
        template.setStatus(status);
        FreightTemplateRo ro = new FreightTemplateRo();
        CopyUtils.copyProperties(template, ro);
        delayer.executeAfterTransactionCommit(() -> freightTemplateRedisDao.save(ro));
    }

    /**
     * 获取详情
     *
     * @param id 模板id
     */
    public FreightTemplateDetailRespVo detail(Long id) {
        AssertUtils.notNull(id, DepotException.FREIGHT_ID_IS_NULL);
        FreightTemplate template = freightTemplateRepository.findOne(id);
        AssertUtils.notNull(template, DepotException.FREIGHT_NOT_EXISTS);
        FreightTemplateDetailRespVo resp = new FreightTemplateDetailRespVo();
        CopyUtils.copyProperties(template, resp);
        return resp;
    }

    /**
     * 校验运费编码是否唯一
     *
     * @param id          运费模板ID
     * @param freightCode 运费模板编号
     * @return 唯一返回true 反之返回false
     */
    public Boolean checkCodeExists(Long id, String freightCode) {
        if (id == null || StringUtils.isBlank(freightCode)) {
            return true;
        }
        FreightTemplate template = freightTemplateRepository.findByFreightCode(freightCode);
        return Objects.equals(template.getId(), id);
    }

    public Integer getPrice(String freightCode, Integer totalWeight) {
        FreightTemplateRo freightTemplateRo = freightTemplateRedisDao.findByCode(freightCode);
        AssertUtils.notNull(freightTemplateRo, DepotException.FREIGHT_NOT_EXISTS);
        Integer baseCost = freightTemplateRo.getBaseCost();
        Integer stepCost = freightTemplateRo.getStepCost();
        Integer baseWeight = freightTemplateRo.getBaseWeight();
        Integer stepWeight = freightTemplateRo.getStepWeight();

        Integer stepTotalWeight = totalWeight - baseWeight;
        if (stepTotalWeight <= 0) {
            return baseCost;
        }
        Integer stepCount = new BigDecimal(stepTotalWeight).divide(new BigDecimal(stepWeight), RoundingMode.UP).intValue();
        return stepCount * stepCost + baseCost;
    }

}